package com.cqsd.ioc.core.context;

import com.cqsd.ioc.annotation.ApplicationConfig;
import com.cqsd.ioc.annotation.Component;
import com.cqsd.ioc.annotation.SystemEnv;
import com.cqsd.ioc.core.bean.BeanDef;
import com.cqsd.ioc.core.factory.AppFactory;
import com.cqsd.ioc.env.Env;
import com.cqsd.ioc.env.EnvImpl;
import com.cqsd.ioc.trait.BeanInfo;
import com.cqsd.ioc.trait.use.DestructFunction;
import com.cqsd.ioc.util.RunTimeUtil;
import com.cqsd.string.StringUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;


/**
 * @author caseycheng
 * 负责存储
 * @date 2023/3/23-12:04
 **/
abstract public class BaseContext extends AppFactory {
    private static final Logger log = LogManager.getLogger(BaseContext.class);
    /**
     * 程序的环境
     */
    private final Env appEnv = new EnvImpl();
    /**
     * 存储Bean定义信息还有单例池
     */
    private final BeanManager beanManager = BeanManager.getInstance();
    /**
     * 销毁时的钩子
     */
    private final List<DestructFunction> destructFunctionList = new ArrayList<>();

    /**
     * 初始化Env环境
     *
     * @param configClass
     */
    void initEnvConfig(ApplicationConfig configClass) {
        //获取应用程序配置
        //加载资源配置
        log.info("正在解析配置文件");
        //解析配置文件
        appEnv.parseProperties(configClass.propertiesPath());
        //存在SystemEnv注解的时候解析系统配置
        //解析系统配置
        if (configClass.value().isAnnotationPresent(SystemEnv.class)) {
            log.info("开始解析系统配置");
            appEnv.parseSystemEnv();
        }
        //解析yaml配置
        appEnv.parseYaml(configClass.yamlPath());
        log.info("配置文件解析完毕");
    }

    /**
     * 解析一个class对象
     *
     * @param clazz
     */
    @Override
    public void loadClass(Class<?> clazz) {
        //使用set记录已解析到的class集合，防止重复提交
        if (beanManager.contains(clazz)) {
            return;
        }
        //排除注解和枚举
        if (clazz.isEnum()) {
            return;
        }
        if (clazz.isAnnotation()) {
            return;
        }
        final var manager = this.getBeanInfoManager();
        BeanInfo beanInfo;
        String beanName;
        if (clazz.isAnnotationPresent(Component.class)) {
            //作用域检查在BeanDef里
            beanInfo = new BeanDef(clazz);
            beanName = clazz.getAnnotation(Component.class).value();
            if ("".equals(beanName)) {
                beanName = StringUtil.toLowerCase(clazz.getSimpleName());
            }
            beanInfo.setName(beanName);
            log.debug("已为{}对象分配beanName:{}", clazz.getSimpleName(), beanName);
            manager.add(beanInfo);
        }
    }


    @Override
    public Env getAppEnv() {
        return appEnv;
    }

    @Override
    public Map<String, BeanInfo> getBeanInfoMap() {
        return beanManager.beanNameInfoMap();
    }

    /**
     * 初始化程序关闭回调
     */
    protected void initShutdownHook() {
        RunTimeUtil.addShutdownHook(() -> {
            for (DestructFunction destructFunction : this.destructFunctionList) {
                destructFunction.destruct();
            }
        }, "Recover");
    }

    public void addDestruct(DestructFunction destructFunction){
        this.destructFunctionList.add(destructFunction);
    }

    /**
     * 获取beanInfo容器
     *
     * @return
     */
    @Override
    public BeanManager getBeanInfoManager() {
        return this.beanManager;
    }
}
